package legato.tasks
{
	import flash.events.Event;
	
	import legato.actions.*;
	
	import mx.collections.ArrayCollection;

	/**
	 * A singleton class used to execute all tasks and actions. It can save copy of actions as an action history.
	 * @author Piotr
	 * 
	 */
	public class TaskManager 
	{
		private static var _instance:TaskManager = null;
		/**
		 * A single instance.
		 * @return 
		 * 
		 */		
		public static function get instance():TaskManager
		{
			if (_instance == null)
			{
				_instance = new TaskManager();
			}
			return _instance;
		}
		
		private var tasksQueue:Array;
		
		private var _actionHistory:ArrayCollection;

		/**
		 * Constructor 
		 * 
		 */
		public function TaskManager()
		{
			this._actionHistory = new ArrayCollection(); 
			this.tasksQueue = [];
		}
		
		[Bindable]
		/**
		 * History of executed actions. Contains copies of ation objects. 
		 * @param val
		 * 
		 */
		public function set actionHistory(val:ArrayCollection):void
		{
			_actionHistory = val;
		}

		public function get actionHistory():ArrayCollection
		{
			return _actionHistory;
		}
		
		
		/**
		 * Executes given task.
		 * @param task taks to be executed
		 * 
		 */
		public function executeTask(task:ITask):void
		{
			this.pushTask(task);
			task.addEventListener(Event.COMPLETE,this.taskCompleteEventHandler);
			task.execute();
		} 
		
		/**
		 * Executes given action. If <code>action.saveCopy</code> is set to 
		 * true - action is copied before execution and saved in history. 
		 * @param action an action object to be executed 
		 * 
		 */
		public function executeAction(action:IAction):void
		{
			if (action.saveCopy)
			{
				var actionCopy:IAction = action.createCopy();
				this.actionHistory.addItem(actionCopy);
				actionCopy.addEventListener(Event.COMPLETE,this.taskCompleteEventHandler);
				actionCopy.execute();
			}
			else
			{
				action.addEventListener(Event.COMPLETE,this.taskCompleteEventHandler);
				action.execute();
			}
		}
		
		public function pushTask(task:ITask):void
		{
			this.tasksQueue.push(task);
		}
		
		public function queueTask(task:ITask):void
		{
			this.tasksQueue.unshift(task);
		}
		
		public function executeQueue():void
		{
			
			if (this.tasksQueue.length > 0)
			{
				var t:ITask = this.tasksQueue.pop();
				if (t is IAction)
				{
					this.executeAction(IAction(t));
				}
				else
				{
					this.executeTask(ITask(t));
				}
			}
		}
		
		
		private function taskCompleteEventHandler(event:Event):void
		{
			var index:int = this.tasksQueue.indexOf(event.target);
			if (index >= 0)
			{
				this.tasksQueue.removeItemAt(index);
			}
			this.executeQueue();
		}
		

	}
}